﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RayTracing
{
    class ShiftedObject : Geometry
    {
        public Geometry geometry; //Geometry of the object

        public string s;
        public float[] mIn = P3.iMatrix();
        public float[] mOut = P3.iMatrix();


        public ShiftedObject(Geometry geometry) //Creates a SceneObject with a geometry, texture, and skin
        {
            this.geometry = geometry;
            //P3 unscale = new P3(1 / scale.x, 1 / scale.y, 1 / scale.z);
            //P3 unhpr = new P3(-hpr.x, -hpr.y, -hpr.z);
            //P3 unxyz = new P3(-xyz.x, -xyz.y, -xyz.z);

        }

        public void translate(P3 xyz)
        {
            mIn = P3.matrixMult(mIn, P3.moveGen(xyz));
            mOut = P3.matrixMult(P3.moveGen(P3.scale(xyz, -1)), mOut);
        }

        public void scale(P3 sc)
        {
            mIn = P3.matrixMult(mIn, P3.scaleGen(sc));
            mOut = P3.matrixMult(P3.scaleGen(new P3(1 / sc.x, 1 / sc.y, 1 / sc.z)), mOut);
        }

        public void rotate(P3 hpr)
        {
            mIn = P3.matrixMult(mIn, P3.hprGen(hpr, false));
            mOut = P3.matrixMult(P3.hprGen(hpr, true), mOut);
        }


        public P3 toInnerP(P3 p)
        {
            P3 newp = P3.multP3Matrix(p, mIn);
            return newp;
        }

        public P3 toOuterP(P3 p)
        {
            P3 newp = P3.multP3Matrix(p, mOut);
            return newp;
        }

        public P3 toInnerD(P3 p)
        {
            P3 newp = P3.multDirMatrix(p, mIn);
            return newp;
        }
        public P3 toOuterD(P3 p)
        {
            P3 newp = P3.multDirMatrix(p, mOut);
            return newp;
        }


        public float distance(Ray ray)         //Gets the distance of a ray using geometry
        {
            Ray newray = new Ray(toInnerP(ray.origin), P3.normalize(toInnerD(ray.direction)));

            float dist = geometry.distance(newray);

            if (dist == Main.infinity)
            {
                return dist;
            }
            P3 innerP3 = newray.travel(dist);

            P3 outerP3 = toOuterP(innerP3);

            return P3.norm(P3.sub(outerP3, ray.origin));
        }

        public P2 toP2(P3 p)
        {
            P3 newp = toInnerP(p);
            return geometry.toP2(newp);
        }
        public P3 normal(P3 p)
        {
            P3 newp = toInnerP(p);

            newp = geometry.normal(newp);

            return toOuterP(newp);

        }

    }
}